package com.sc.nft.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.dao.MallActivityRankingCyclesDao;
import com.sc.nft.dao.MallActivityRankingDao;
import com.sc.nft.entity.EcologyPoolCommunityServiceRankIncomeConditionConf;
import com.sc.nft.entity.MallActivityRanking;
import com.sc.nft.entity.MallActivityRankingCycles;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.MallActivityRankingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 排行榜配置
 *
 * @author zxy
 * @description IP商城
 * @since 2023-05-10 16:59:01
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class MallActivityRankingServiceImpl implements MallActivityRankingService {

    private final MallActivityRankingDao mallActivityRankingDao;
    private final MallActivityRankingCyclesDao mallActivityRankingCyclesDao;

    @Override
    public IPage<MallActivityRanking> queryActivityRankingPage(Page toMp) {
        LambdaQueryWrapper<MallActivityRanking> queryWrapper =  new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(MallActivityRanking::getCreateTime);
        return mallActivityRankingDao.page(toMp, queryWrapper);
    }


    @Override
    public Boolean save(MallActivityRanking mallActivityRanking) {
        Assert.isTrue(!mallActivityRanking.getStartTime().before(new Date()), () -> new GlobalRunTimeException("开始时间不能早于当前时间！"));

        Boolean success = mallActivityRankingDao.save(mallActivityRanking);
        if (success) {
            List<MallActivityRankingCycles> mallActivityRankingCyclesList = generateCycles(mallActivityRanking.getStartTime(), mallActivityRanking.getEndTime(), mallActivityRanking.getPeriodDays(), mallActivityRanking.getId(), mallActivityRanking.getThresholdAmount());
            mallActivityRankingCyclesDao.saveBatch(mallActivityRankingCyclesList);
        }
        return true;
    }

    @Override
    public Boolean update(MallActivityRanking mallActivityRanking) {
        if (mallActivityRanking.getStatus()) {
            LambdaUpdateWrapper<MallActivityRanking> wrapper = new LambdaUpdateWrapper<>();
            wrapper.set(MallActivityRanking::getStatus, false);
            mallActivityRankingDao.update(null,wrapper);
        }
        if(mallActivityRanking.getThresholdAmount() != null && mallActivityRanking.getThresholdAmount().compareTo(BigDecimal.ZERO) > 0){
            List<MallActivityRankingCycles> mallActivityRankingCyclesList =  mallActivityRankingCyclesDao.queryRankingCyclesByRankingId(mallActivityRanking.getId());
            for (MallActivityRankingCycles mallActivityRankingCycles : mallActivityRankingCyclesList) {
                mallActivityRankingCycles.setThresholdAmount(mallActivityRanking.getThresholdAmount());
            }
            mallActivityRankingCyclesDao.saveBatch(mallActivityRankingCyclesList);
        }
        return mallActivityRankingDao.updateById(mallActivityRanking);
    }


    public static List<MallActivityRankingCycles> generateCycles(Date startDate, Date endDate, int cycleLength, Long rankingId, BigDecimal thresholdAmount) {
        List<MallActivityRankingCycles> cycles = new ArrayList<>();

        boolean isFirstCycle = true;
        while (startDate.before(endDate)) {
            Date currentEndDate = new Date(startDate.getTime() + TimeUnit.DAYS.toMillis(cycleLength - 1));
            if (currentEndDate.after(endDate)) {
                currentEndDate = endDate;
            }

            // 处理第一个周期
            if (isFirstCycle) {
                currentEndDate = setEndTimeTo235959(currentEndDate);
                isFirstCycle = false;
            } else {
                // 非第一个周期，设置开始时间为00:00:00
                startDate = setStartTimeTo000000(startDate);
                if (!currentEndDate.equals(endDate)) {
                    currentEndDate = setEndTimeTo235959(currentEndDate);
                }
            }

            cycles.add(new MallActivityRankingCycles(startDate, currentEndDate, rankingId, thresholdAmount));
            startDate = new Date(currentEndDate.getTime() + TimeUnit.DAYS.toMillis(1));
        }

        // 如果最后一个周期的结束时间不是endDate，则重新计算最后一个周期
        if (!cycles.isEmpty() && !cycles.get(cycles.size() - 1).getEndTime().equals(endDate)) {
            MallActivityRankingCycles lastCycle = cycles.remove(cycles.size() - 1);
            cycles.add(new MallActivityRankingCycles(lastCycle.getStartTime(), endDate, rankingId, thresholdAmount));
        }

        return cycles;
    }


    private static Date setEndTimeTo235959(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date startOfDay = sdf.parse(sdf.format(date));
            return new Date(startOfDay.getTime() + TimeUnit.DAYS.toMillis(1) - 1);
        } catch (ParseException e) {
            throw new RuntimeException("Failed to set end time to 23:59:59", e);
        }
    }

    private static Date setStartTimeTo000000(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static void main(String[] args) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startDate;
        Date endDate;

        try {
            startDate = formatter.parse("2024-09-01 10:10:10");
            endDate = formatter.parse("2024-09-10 20:10:10");
        } catch (ParseException e) {
            e.printStackTrace();
            return;
        }

        int cycleLength = 2;

        List<MallActivityRankingCycles> cycles = generateCycles(startDate, endDate, cycleLength, 1L, BigDecimal.ZERO);

        for (MallActivityRankingCycles cycle : cycles) {
            System.out.println(cycle);
        }
    }


}